package com.atguigu.gmall.web.all.service.impl;


import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.feign.cart.CartFeignClient;
import com.atguigu.gmall.feign.product.SkuInfoFeignClient;
import com.atguigu.gmall.feign.user.UserFeignClient;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.web.all.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class OrderServiceImpl implements OrderService {

    @Autowired
    CartFeignClient cartFeignClient;

    @Autowired
    UserFeignClient userFeignClient;

    @Autowired
    SkuInfoFeignClient skuInfoFeignClient;

    @Autowired
    StringRedisTemplate redisTemplate;



    @Override
    public Map<String, Object> getOrderConfirmInfo(String userId) {
        //从controller---service的主线程的request信息
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HashMap<String, Object> map = new HashMap<>();

        //多线程要操作，使用AtomicInteger 防止并发，必须不可变类
        final BigDecimal[] totalAmount = {new BigDecimal("0.0")};
        final AtomicInteger totalNum = new AtomicInteger(0);

        //1、TODO 远程查询购物车服务，获取到购物车选中的所有商品列表
        CompletableFuture<List<CartInfo>> listCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //自己异步线程把老请求放进去，解决feign异步请求丢失请求头信息问题
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<CartInfo> detailArrayList = cartFeignClient.cartListChecked();

            return detailArrayList;
        });
        //2、TODO 计算总价
        CompletableFuture<List<CartInfo>> priceAndNumFuture = listCompletableFuture.whenCompleteAsync((result, execption) -> {
            //自己异步线程把老请求放进去
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<CartInfo> infos = new ArrayList<>();
            for (CartInfo cartInfo : result) {
                //总价 = 数量 * 单价
                //当前数量
                Integer skuNum = cartInfo.getSkuNum();
                totalNum.addAndGet(skuNum); //叠加数量
                //3、TODO 查询到最新的价格
                BigDecimal skuPrice = skuInfoFeignClient.getSkuPrice(cartInfo.getSkuId());
                cartInfo.setSkuPrice(skuPrice);
                BigDecimal multiply = skuPrice.multiply(new BigDecimal(skuNum.toString()));
                totalAmount[0] = totalAmount[0].add(multiply);
                infos.add(cartInfo);

            }
            map.put("detailArrayList",infos);
            map.put("totalAmout",totalAmount);
            map.put("totalNum",totalNum);
        });
        CompletableFuture<List<UserAddress>> addressFuture = CompletableFuture.supplyAsync(() -> {
            //自己异步线程把老请求放进去
            RequestContextHolder.setRequestAttributes(requestAttributes);
            //3、TODO 远程查询用户的所有收获地址列表
            List<UserAddress> address = userFeignClient.getCurrentUserAddress();
            map.put("userAddressList",address);
            return address;
        });

        

        //4、TODO 页面需要 tradeNo，页面用来做防重复提交的
        final CompletableFuture<Void> tokenFuture = CompletableFuture.runAsync(() -> {
            //后台生成的防重复令牌
            String token = UUID.randomUUID().toString().replace("-", "");
            redisTemplate.opsForValue().set(RedisConst.USER_UNREPEAT_TOKEN + userId, token, RedisConst.USER_UNREPEAT_TOKEN_TTL, TimeUnit.SECONDS);
            map.put("tradeNo", token);

        });

        CompletableFuture.allOf(addressFuture,listCompletableFuture,priceAndNumFuture,tokenFuture)
                .join();

        /**
         * detailArrayList: 商品清单（拿到购物车中已经选中的这些商品） 【给service-cart\给service-product】
         *          每个商品：imgUrl、skuName、OrderPrice、skuNum
         * totalNum: 商品数量: 自己计算
         * totalAmount： 商品金额：自己计算
         * userAddressList： 用户收获地址列表  给【service-user】
         * tradeNo 交易号【防止重复提交的】 给【service-order】发请求
         */


        return map;
    }
}
